package org.example;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.AsciiString;
import io.netty.handler.codec.http.*;
import lombok.extern.java.Log;


/**
 * ，负责启动（BootStrap）和main方法，
 * 一个是ChannelHandler，负责具体的业务逻辑，我们先从启动类说起。
 */
@Log
public class HttpServer {
    private final int port  ;

    public HttpServer(Integer port) {
        this.port = port;
    }

    public static void main(String[] args) throws InterruptedException {
        if (args.length != 1) {
            System.err.println("Usage: " + HttpServer.class.getSimpleName() + " <port>");
            return;
        }

        int port = Integer.parseInt(args[0]);
        new HttpServer(port).start();
    }

    public void start() throws InterruptedException {
        ServerBootstrap b = new ServerBootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        b.group(group).channel(NioServerSocketChannel.class)
                .childHandler(new CustChannelInit())
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);
        b.bind(port).sync();
    }

    static class CustChannelInit extends ChannelInitializer<SocketChannel> {
        protected void initChannel(SocketChannel socketChannel) throws Exception {
            log.info("socketChannel--->" + socketChannel);
            socketChannel.pipeline()
                    .addLast("decoder", new HttpRequestDecoder())//解码req
                    .addLast("encoder", new HttpResponseEncoder())//编码res
                    .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
                    .addLast("handler", new HttpHandler());
        }
    }

    static class HttpHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
        private AsciiString contentType = HttpHeaderValues.TEXT_PLAIN;

        protected void messageReceived(ChannelHandlerContext channelHandlerContext, FullHttpRequest fullHttpRequest) throws Exception {
            log.info("class--" + fullHttpRequest.getClass().getName());
            DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, Unpooled.wrappedBuffer("test".getBytes()));
            HttpHeaders headers = defaultFullHttpResponse.headers();
            headers.add(HttpHeaderNames.CONTENT_TYPE, contentType + "; charset=UTF-8");
            headers.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
            headers.addInt(HttpHeaderNames.CONTENT_LENGTH, defaultFullHttpResponse.content().readableBytes());
            channelHandlerContext.write(defaultFullHttpResponse);
        }

        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            log.info("channelReadComplete");
            super.channelReadComplete(ctx);
            ctx.flush();
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            log.info("exceptionCaught");
            if (null != cause) cause.printStackTrace();
            if (null != ctx) ctx.close();
        }
    }
}
